from time import time

from api import *
from base import *
from im_engine import PimeEngine
from im_key_event import *


def _createImKeyEvent(key_event) -> ImKeyEvent:
    event = ImKeyEvent()
    event.apply(key_event.keyCode, key_event.charCode)
    return event


class PimeImpl(ImService):

    def __init__(self, pime_text_service) -> None:
        super().__init__()
        self.pime = pime_text_service
        self.engine = PimeEngine()
        self.workDir = Dirs.here
        self.dataDir = Dirs.fileInHere('data')
        print('workDir:{}'.format(self.workDir))
        print('dataDir:{}'.format(self.dataDir))
        self.engine.useImService(self)
        self.state = CandidateState()
        self.firstKeyDown = 0
        self.imKeyEvent = ImKeyEvent()
        self.lastKeyDownTime = 0.0  # 最后一次检测到按键按下的时间

    def applyTheme(self, style):
        # style = pimeConfig.get('candidateBar')  # 将字典作为命名参数传递给函数的方法
        self.pime.customizeUI(**style)

    def getWorkDir(self):
        return self.workDir

    def getDataDir(self):
        return self.dataDir

    # 檢查設定檔是否有被更改，是否需要套用新設定
    def checkConfigChange(self):
        print('>>> <{}> checkConfigChange().'.format(__name__))
        # self.applyTheme()

    def onActivate(self):
        """
        输入法被激活
        """
        print('>>> <{}> onActivate().'.format(__name__))
        self.engine.onActivate()

    def onDeactivate(self):
        """
        用户离开输入法
        """
        print('>>> <{}> onDeactivate().'.format(__name__))
        self.engine.onDeactivate()

    def showTooltip(self, text: str, timeout: int = 1):
        self.pime.showMessage(text, timeout)

    def setComposition(self, composition: str):
        self.state.composition = composition
        print('>>> <{}> setComposition(`{}`)'.format(__name__, composition))
        self.pime.setCompositionString(composition)
        # self._updateUI(self.state.hasComposition())

    def showCandidates(self, state: CandidateState):
        self.state = state
        self._updateUI(True)

    def hideCandidates(self):
        self._updateUI(False)

    def commit(self, text=''):
        print('>>> <{}> commit(`{}`)'.format(__name__, text))
        self.pime.setCommitString(text)

    def filterKeyDown(self, key_event):
        print(
            '>>> <{}> filterKeyDown(), keyCode={}, charCode={}'.format(__name__, key_event.keyCode,
                                                                       key_event.charCode))
        now = time()
        ctrl = key_event.isKeyDown(VK_CONTROL)
        shift = key_event.isKeyDown(VK_SHIFT)
        alt = key_event.isKeyDown(VK_MENU)
        if self.firstKeyDown == 0:
            self.firstKeyDown = key_event.keyCode
            self.imKeyEvent = ImKeyEvent()
        self.imKeyEvent.updateModifiers(ctrl, shift, alt)
        self.imKeyEvent.apply(key_event.keyCode, key_event.charCode)
        rtn = self.engine.testKeyDown(self.imKeyEvent)
        print('>>> <{}> filterKeyDown return: {}'.format(__name__, rtn))
        self.lastKeyDownTime = now
        return rtn

    def filterKeyUp(self, key_event):
        print('>>> <{}> filterKeyUp(), keyCode={}, charCode={}'.format(__name__, key_event.keyCode, key_event.charCode))
        if self.imKeyEvent.value == 0:  # 出现在刚切换的时候
            print('>>> filterKeyUp return: false')
            return False
        # print('>>> before filterKeyUp(), imKeyEvent:{}'.format(self.imKeyEvent))
        # rtn = self.engine.onKeyUp(self.imKeyEvent)
        # if key_event.keyCode == self.firstKeyDown:  # 按键序列完成，重置按键，进入下一轮检测
        #     self.firstKeyDown = 0
        # elif key_event.charCode == 0 and (key_event.keyCode in [VK_CONTROL, VK_SHIFT, VK_MENU]):  # 移除修饰键
        #     if key_event.keyCode in [VK_CONTROL, VK_SHIFT, VK_MENU]:
        #         self.imKeyEvent.release(key_event.keyCode)
        # else:  # 移除普通键
        #     self.imKeyEvent.apply()
        # print('>>> after filterKeyUp(), imKeyEvent:{}, rtn:{}'.format(self.imKeyEvent, rtn))
        return True

    def onKeyDown(self, key_event):
        rtn = self.engine.onKeyDown(self.imKeyEvent)
        print('>>> <{}> onKeyDown return: {}'.format(__name__, rtn))
        return rtn

    def onKeyUp(self, key_event):
        rtn = self.engine.onKeyUp(self.imKeyEvent)
        print('>>> <{}> onKeyUp return: {}'.format(__name__, rtn))
        if key_event.keyCode == self.firstKeyDown:  # 按键序列完成，重置按键，进入下一轮检测
            self.firstKeyDown = 0
        elif key_event.charCode == 0 and (key_event.keyCode in [VK_CONTROL, VK_SHIFT, VK_MENU]):  # 移除修饰键
            if key_event.keyCode in [VK_CONTROL, VK_SHIFT, VK_MENU]:
                self.imKeyEvent.release(key_event.keyCode)
        else:  # 移除普通键
            self.imKeyEvent.apply()
        return rtn

    def onPreservedKey(self, guid):
        print('>>> <{}> onPreservedKey(), guid={}'.format(__name__, guid))
        return True

    def onCommand(self, command_id, command_type):
        print('>>> onCommand({}, {})'.format(command_id, command_type))
        return True

    # 開啟語言列按鈕選單
    def onMenu(self, button_id):
        print('>>> onMenu(), button_id={}.'.format(button_id))
        return None

    def onKeyboardStatusChanged(self, opened):
        print('>>> onKeyboardStatusChanged(), opened={}.'.format(opened))
        return False

    # 當中文編輯結束時會被呼叫。若中文編輯不是正常結束，而是因為使用者
    # 切換到其他應用程式或其他原因，導致我們的輸入法被強制關閉，此時
    # forced 參數會是 True，在這種狀況下，要清除一些 buffer
    def onCompositionTerminated(self, forced):
        print('>>> <{}> onCompositionTerminated(), forced={}.'.format(__name__, forced))
        if forced:
            self.engine.stop()

    def _updateUI(self, show=False):
        pime = self.pime
        cs = self.state
        print('>>> _updateUI, setCompositionString=`{}`'.format(cs.composition))
        pime.setCompositionString(cs.composition)
        pime.setCompositionCursor(len(cs.composition))
        pime.setCandidateCursor(cs.candidateCursor)  # 选中的候选索引，可以通过光标来移动
        if show:
            print('>>> _updateUI, showCandidates')
            candidateList = []
            if cs.hasCandidate():
                for i in range(0, cs.count()):
                    candidateList.append(cs.candidateTextAt(i, comment_prefix='~'))
            pime.setCandidateList(candidateList)
        else:
            print('>>> _updateUI, hideCandidates')
        pime.setShowCandidates(show)
